home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / scsiDiskBoot / RCS / fs.c,v < prev    next >
Encoding:
Text File  |  1989-06-16  |  14.9 KB  |  700 lines

  1. head     1.9;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    mendel:1.9; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.9
  10. date     89.06.16.08.29.57;  author brent;  state Exp;
  11. branches ;
  12. next     1.8;
  13.  
  14. 1.8
  15. date     89.01.06.08.14.31;  author brent;  state Exp;
  16. branches ;
  17. next     1.7;
  18.  
  19. 1.7
  20. date     87.05.19.12.14.02;  author brent;  state Exp;
  21. branches ;
  22. next     1.6;
  23.  
  24. 1.6
  25. date     87.05.11.11.16.35;  author brent;  state Exp;
  26. branches ;
  27. next     1.5;
  28.  
  29. 1.5
  30. date     87.05.08.17.44.41;  author brent;  state Exp;
  31. branches ;
  32. next     1.4;
  33.  
  34. 1.4
  35. date     86.07.24.11.32.59;  author brent;  state Exp;
  36. branches ;
  37. next     1.3;
  38.  
  39. 1.3
  40. date     86.07.21.09.35.02;  author brent;  state Exp;
  41. branches ;
  42. next     1.2;
  43.  
  44. 1.2
  45. date     86.07.18.11.58.21;  author nelson;  state Exp;
  46. branches ;
  47. next     1.1;
  48.  
  49. 1.1
  50. date     86.07.18.09.32.17;  author brent;  state Exp;
  51. branches ;
  52. next     ;
  53.  
  54.  
  55. desc
  56. @Boot time filesystem utilities
  57. @
  58.  
  59.  
  60. 1.9
  61. log
  62. @Updated to the new device interface
  63. @
  64. text
  65. @/* fs.c -
  66.  *
  67.  *    General filesystem support.
  68.  *
  69.  * Copyright (C) 1985 Regents of the University of California
  70.  * All rights reserved.
  71.  */
  72.  
  73. #ifdef notdef
  74. static char rcsid[] = "$Header: /sprite/src/boot/scsiDiskBoot/RCS/fs.c,v 1.8 89/01/06 08:14:31 brent Exp $ SPRITE (Berkeley)";
  75. #endif not lint
  76.  
  77. #include "sprite.h"
  78. #include "fsBoot.h"
  79. #include "machMon.h"
  80.  
  81. /*
  82.  * For non-block aligned reads.
  83.  */
  84. char    readBuffer[FS_BLOCK_SIZE];
  85.  
  86. /*
  87.  * For lookup
  88.  */
  89. static char    component[FS_MAX_NAME_LENGTH];
  90.  
  91. /*
  92.  * Forward declarations.
  93.  */
  94. void FsGetFileDesc();
  95. void FsInitFileHandle();
  96. #undef NO_PRINTF
  97.  
  98. /*
  99.  * ----------------------------------------------------------------------------
  100.  *
  101.  * Fs_Open --
  102.  *
  103.  *    Open a file.  This does a simple lookup (based on the kernel's
  104.  *    FsLocalLookup) and creates a handle for the file.
  105.  *
  106.  * Results:
  107.  *    SUCCESS or a return code from various sub-operations.
  108.  *
  109.  * Side effects:
  110.  *    Calls malloc
  111.  *
  112.  * ----------------------------------------------------------------------------
  113.  */
  114.  
  115. ReturnStatus
  116. Fs_Open(fileName, useFlags, permissions, handlePtrPtr)
  117.     char *fileName;
  118.     int useFlags;
  119.     int permissions;
  120.     FsLocalFileIOHandle     **handlePtrPtr;
  121. {
  122.     register ReturnStatus status;
  123.     FsLocalFileIOHandle *curHandlePtr;
  124.     register char *curCharPtr;
  125.     register char *componentPtr;
  126.     register int index;
  127.  
  128.     curCharPtr = fileName;
  129.     while(*curCharPtr == '/') {
  130.     curCharPtr++;
  131.     }
  132.     curHandlePtr = fsRootHandlePtr;
  133.  
  134.     while (*curCharPtr != '\0') {
  135.     if (curHandlePtr->descPtr->fileType != FS_DIRECTORY) {
  136.         return(FS_NOT_DIRECTORY);
  137.     }
  138.         /*
  139.          * Get the next component.
  140.          */
  141.         index = 0;
  142.     componentPtr = component;
  143.         while (*curCharPtr != '/' && *curCharPtr != '\0') {
  144.             *componentPtr++ = *curCharPtr++;
  145.         }
  146.         *componentPtr = '\0';
  147. #ifndef NO_PRINTF
  148.     Mach_MonPrintf(" %s ", component);
  149. #endif
  150.         /*
  151.          * Skip intermediate and trailing slashes so that *curCharPtr
  152.          * is Null when 'component' has the last component of the name.
  153.          */
  154.         while (*curCharPtr == '/') {
  155.             curCharPtr++;
  156.         }
  157.  
  158.     status = FsFindComponent(fsDomainPtr, curHandlePtr, component,
  159.                           &curHandlePtr);
  160.  
  161.     if (status != SUCCESS) {
  162. #ifndef NO_PRINTF
  163.         Mach_MonPrintf("<%x>\n", status);
  164. #endif
  165.         return(status);
  166.     }
  167.     }
  168.     *handlePtrPtr = curHandlePtr;
  169. }
  170.  
  171. /*
  172.  * ----------------------------------------------------------------------------
  173.  *
  174.  * Fs_Read --
  175.  *
  176.  *    Read from a file given its handle.
  177.  *
  178.  * Results:
  179.  *    A return status from the read.
  180.  *
  181.  * Side effects:
  182.  *    buffer is loaded with the data read in.
  183.  *    *readCountPtr is updated to reflect the number of bytes read.
  184.  *
  185.  * ----------------------------------------------------------------------------
  186.  */
  187. ReturnStatus
  188. Fs_Read(handlePtr, offset, numBytes, buffer, readCountPtr)
  189.     register FsLocalFileIOHandle     *handlePtr;
  190.     int            offset;
  191.     int            numBytes;
  192.     register Address    buffer;
  193.     int            *readCountPtr;
  194. {
  195.     int                firstBlock;
  196.     int                lastBlock;
  197.     int                lastByte;
  198.     BlockIndexInfo        indexInfo;
  199.     register    int        readSize;
  200.     register    int        blockAddr;
  201.     register    int        blockOffset;
  202.     register    int        bufferIndex;
  203.     register     ReturnStatus    status;
  204.     register    int        size;
  205.  
  206.     firstBlock = offset / FS_BLOCK_SIZE; 
  207.     lastByte = offset + numBytes - 1;
  208.     if (lastByte > handlePtr->descPtr->lastByte) {
  209.     lastByte = handlePtr->descPtr->lastByte;
  210.     }
  211.     lastBlock = lastByte / FS_BLOCK_SIZE;
  212.  
  213.     (void)FsGetFirstIndex(handlePtr, firstBlock, &indexInfo);
  214.  
  215.     bufferIndex = 0;
  216.     blockOffset = offset & FS_BLOCK_OFFSET_MASK;
  217. #ifdef notdef 
  218.     Mach_MonPrintf(" read %d at %d into %x\n", numBytes, offset, buffer);
  219. #endif notdef 
  220.  
  221.     while (indexInfo.blockNum <= lastBlock) {
  222.     if (indexInfo.blockNum < lastBlock) {
  223.         size = FS_BLOCK_SIZE - blockOffset;
  224.         readSize = FS_BLOCK_SIZE;
  225.     } else {
  226.         size = (lastByte & FS_BLOCK_OFFSET_MASK) + 1 - blockOffset;
  227.         readSize = size;
  228.     }
  229.     blockAddr = *indexInfo.blockAddrPtr + 
  230.             fsDomainPtr->headerPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK;
  231.     if (blockOffset != 0 || size != FS_BLOCK_SIZE) { 
  232.         status = FsDeviceBlockIO(FS_READ, &fsDevice, blockAddr,
  233.                (readSize - 1) / FS_FRAGMENT_SIZE + 1, readBuffer);
  234.         if (status != SUCCESS) {
  235.         goto readError;
  236.         }
  237.         bcopy(&(readBuffer[blockOffset]), &(buffer[bufferIndex]), size);
  238.     } else {
  239.         status = FsDeviceBlockIO(FS_READ, &fsDevice, blockAddr,
  240.             FS_FRAGMENTS_PER_BLOCK, &(buffer[bufferIndex]));
  241.         if (status != SUCCESS) {
  242.         goto readError;
  243.         }
  244.     }
  245.     bufferIndex += size;
  246.     blockOffset = 0;
  247.     FsGetNextIndex(handlePtr, &indexInfo);
  248.     }
  249.  
  250. readError:
  251.  
  252.     *readCountPtr = bufferIndex;
  253.  
  254.     return(status);
  255. }
  256.  
  257. /*
  258.  *----------------------------------------------------------------------
  259.  *
  260.  * FsFindComponent --
  261.  *
  262.  *
  263.  * Results:
  264.  *    None.
  265.  *
  266.  * Side effects:
  267.  *
  268.  *----------------------------------------------------------------------
  269.  */
  270. ReturnStatus
  271. FsFindComponent(domainPtr, curHandlePtr, component, newHandlePtrPtr)
  272.     FsDomain *domainPtr;
  273.     FsLocalFileIOHandle *curHandlePtr;
  274.     char *component;
  275.     FsLocalFileIOHandle **newHandlePtrPtr;
  276. {
  277.     register ReturnStatus status;
  278.     register int dirOffset;        /* Offset within the directory */
  279.     register int blockOffset;        /* Offset within a directory block */
  280.     register FsDirEntry *dirEntryPtr;    /* Reference to directory entry */
  281.     int length;                /* Length variable for read call */
  282.     register FsLocalFileIOHandle *handlePtr;
  283.  
  284.     dirOffset = 0;
  285.     do {
  286.     length = FS_DIR_BLOCK_SIZE;
  287.     status = Fs_Read(curHandlePtr, dirOffset, length, readBuffer, &length);
  288.     if (status != SUCCESS) {
  289.         return(status);
  290.     }
  291.     if (length == 0) {
  292.         return(FS_FILE_NOT_FOUND);
  293.     }
  294.     dirEntryPtr = (FsDirEntry *)readBuffer;
  295.     blockOffset = 0;
  296.     while (blockOffset < FS_DIR_BLOCK_SIZE) {
  297.         dirEntryPtr = (FsDirEntry *)((int)readBuffer + blockOffset);
  298.         if (dirEntryPtr->fileNumber != 0) {
  299.         /*
  300.          * A valid directory record.
  301.          */
  302.         Mach_MonPrintf("Found %s\n", dirEntryPtr->fileName);
  303.         if (strcmp(component, dirEntryPtr->fileName) == 0) {
  304.             handlePtr = (FsLocalFileIOHandle *)malloc(sizeof(FsLocalFileIOHandle));
  305.             FsInitFileHandle(domainPtr, dirEntryPtr->fileNumber,
  306.                     handlePtr);
  307.             *newHandlePtrPtr = handlePtr;
  308.             return(SUCCESS);
  309.         }
  310.         }
  311.         blockOffset += dirEntryPtr->recordLength;
  312.     }
  313.     dirOffset += FS_DIR_BLOCK_SIZE;
  314.     } while(TRUE);
  315. }
  316.  
  317. /*
  318.  *----------------------------------------------------------------------
  319.  *
  320.  * FsInitFileHandle --
  321.  *
  322.  *    Initialize a file handle.
  323.  *
  324.  * Results:
  325.  *    None.
  326.  *
  327.  * Side effects:
  328.  *    Fills in the file handle that our caller has already allocated.
  329.  *
  330.  *----------------------------------------------------------------------
  331.  */
  332. void
  333. FsInitFileHandle(domainPtr, fileNumber, handlePtr)
  334.     FsDomain *domainPtr;
  335.     int fileNumber;
  336.     register FsLocalFileIOHandle *handlePtr;
  337. {
  338.     register FsFileDescriptor *descPtr;
  339.  
  340.     bzero((Address)handlePtr, sizeof(FsLocalFileIOHandle));
  341.     handlePtr->hdr.fileID.minor = fileNumber;
  342.     descPtr = (FsFileDescriptor *)malloc(sizeof(FsFileDescriptor));
  343.     FsGetFileDesc(domainPtr, fileNumber, descPtr);
  344.     handlePtr->descPtr = descPtr;
  345. }
  346.  
  347. /*
  348.  *----------------------------------------------------------------------
  349.  *
  350.  * FsGetFileDesc --
  351.  *
  352.  *    Read in a file descriptor from the disk.
  353.  *
  354.  * Results:
  355.  *    None.
  356.  *
  357.  * Side effects:
  358.  *    Fills in the file descriptor that our caller has already allocated.
  359.  *
  360.  *----------------------------------------------------------------------
  361.  */
  362. void
  363. FsGetFileDesc(domainPtr, fileNumber, descPtr)
  364.     FsDomain *domainPtr;
  365.     register int fileNumber;
  366.     register FsFileDescriptor *descPtr;
  367. {
  368.     register FsDomainHeader *headerPtr;
  369.     register int         blockNum;
  370.     register int         offset;
  371.  
  372.     headerPtr = domainPtr->headerPtr;
  373.     blockNum = headerPtr->fileDescOffset + fileNumber / FS_FILE_DESC_PER_BLOCK;
  374.     offset = (fileNumber & (FS_FILE_DESC_PER_BLOCK - 1)) *
  375.         FS_MAX_FILE_DESC_SIZE;
  376.  
  377.     (void)FsDeviceBlockIO(FS_READ, &fsDevice, 
  378.                blockNum * FS_FRAGMENTS_PER_BLOCK,
  379.                FS_FRAGMENTS_PER_BLOCK, readBuffer);
  380.     bcopy( readBuffer + offset, descPtr, sizeof(FsFileDescriptor));
  381. #ifndef NO_PRINTF
  382.     if (descPtr->magic != FS_FD_MAGIC) {
  383.     Mach_MonPrintf("desc %d bad <%x>\n", fileNumber, descPtr->magic);
  384.     }
  385. #endif
  386. }
  387. @
  388.  
  389.  
  390. 1.8
  391. log
  392. @New include files and constants due to source reorganization
  393. @
  394. text
  395. @d9 2
  396. a10 2
  397. #ifndef lint
  398. static char rcsid[] = "$Header: fs.c,v 1.7 87/05/19 12:14:02 brent Exp $ SPRITE (Berkeley)";
  399. d14 2
  400. a15 4
  401. #include "fs.h"
  402. #include "fsDisk.h"
  403. #include "fsIndex.h"
  404. #include "fsOpTable.h"
  405. a17 7
  406.  * Things set up by Fs_AttachDisk
  407.  */
  408. extern    Fs_Device    fsDevice;
  409. extern    FsDomain    *fsDomainPtr;
  410. extern    FsHandle    *fsRootHandlePtr;
  411.  
  412. /*
  413. d32 1
  414. a32 1
  415.  
  416. d46 1
  417. a46 1
  418.  *    Calls Mem_Alloc
  419. d56 1
  420. a56 1
  421.     FsHandle     **handlePtrPtr;
  422. d59 1
  423. a59 1
  424.     FsHandle *curHandlePtr;
  425. d71 1
  426. a71 1
  427.     if (curHandlePtr->fileType != FS_DIRECTORY) {
  428. d84 1
  429. a84 1
  430.     Sys_Printf(" %s ", component);
  431. d99 1
  432. a99 1
  433.         Sys_Printf("<%x>\n", status);
  434. d125 1
  435. a125 1
  436.     register FsHandle     *handlePtr;
  437. d144 2
  438. a145 2
  439.     if (lastByte > handlePtr->lastByte) {
  440.     lastByte = handlePtr->lastByte;
  441. d154 1
  442. a154 1
  443.     Sys_Printf(" read %d at %d into %x\n", numBytes, offset, buffer);
  444. d168 1
  445. a168 1
  446.         status = FsBlockIO(FS_READ, &handlePtr->device, blockAddr,
  447. d173 1
  448. a173 1
  449.         Byte_Copy(size, &(readBuffer[blockOffset]), &(buffer[bufferIndex]));
  450. d175 1
  451. a175 1
  452.         status = FsBlockIO(FS_READ, &handlePtr->device, blockAddr,
  453. d209 1
  454. a209 1
  455.     FsHandle *curHandlePtr;
  456. d211 1
  457. a211 1
  458.     FsHandle **newHandlePtrPtr;
  459. d218 1
  460. a218 1
  461.     register FsHandle *handlePtr;
  462. d238 3
  463. a240 2
  464.         if (String_Compare(component, dirEntryPtr->fileName) == 0) {
  465.             handlePtr = (FsHandle *)Mem_Alloc(sizeof(FsHandle));
  466. d272 1
  467. a272 1
  468.     register FsHandle *handlePtr;
  469. d276 3
  470. a278 3
  471.     Byte_Zero(sizeof(FsHandle), (Address)handlePtr);
  472.     handlePtr->fileNumber = fileNumber;
  473.     descPtr = (FsFileDescriptor *)Mem_Alloc(sizeof(FsFileDescriptor));
  474. a280 3
  475.     handlePtr->device = fsDevice;
  476.     handlePtr->fileType = descPtr->fileType;
  477.     handlePtr->lastByte = descPtr->lastByte;
  478. d313 1
  479. a313 1
  480.     (void)FsBlockIO(FS_READ, &headerPtr->device, 
  481. d316 1
  482. a316 1
  483.     Byte_Copy(sizeof(FsFileDescriptor), readBuffer + offset, descPtr);
  484. d319 1
  485. a319 1
  486.     Sys_Printf("desc %d bad <%x>\n", fileNumber, descPtr->magic);
  487. @
  488.  
  489.  
  490. 1.7
  491. log
  492. @More trimming to save space.  The Index operations always return
  493. SUCCESS so there's no need to check their return code.
  494. @
  495. text
  496. @d10 1
  497. a10 1
  498. static char rcsid[] = "$Header: fs.c,v 1.6 87/05/11 11:16:35 brent Exp $ SPRITE (Berkeley)";
  499. a14 1
  500. #include "fsInt.h"
  501. a15 1
  502. #include "fsLocalDomain.h"
  503. d80 1
  504. a80 1
  505.     if (curHandlePtr->rec.fileType != FS_DIRECTORY) {
  506. d153 2
  507. a154 2
  508.     if (lastByte > handlePtr->rec.lastByte) {
  509.     lastByte = handlePtr->rec.lastByte;
  510. d177 1
  511. a177 1
  512.         status = FsBlockIO(FS_READ, &handlePtr->rec.device, blockAddr,
  513. d184 1
  514. a184 1
  515.         status = FsBlockIO(FS_READ, &handlePtr->rec.device, blockAddr,
  516. d285 1
  517. a285 1
  518.     handlePtr->rec.fileID.fileNumber = fileNumber;
  519. d288 4
  520. a291 4
  521.     handlePtr->nameToken = (ClientData)descPtr;
  522.     handlePtr->rec.device = fsDevice;
  523.     handlePtr->rec.fileType = descPtr->fileType;
  524.     handlePtr->rec.lastByte = descPtr->lastByte;
  525. @
  526.  
  527.  
  528. 1.6
  529. log
  530. @Trimmed down version that works.
  531. @
  532. text
  533. @d10 1
  534. a10 1
  535. static char rcsid[] = "$Header: fs.c,v 1.5 87/05/08 17:44:41 brent Exp $ SPRITE (Berkeley)";
  536. d160 1
  537. a160 4
  538.     status = FsGetFirstIndex(handlePtr, firstBlock, &indexInfo);
  539.     if (status != SUCCESS) {
  540.     return(status);
  541.     }
  542. d314 1
  543. a314 1
  544.     int fileNumber;
  545. @
  546.  
  547.  
  548. 1.5
  549. log
  550. @Updated to reflect new fs data structures (handle changed)
  551. @
  552. text
  553. @d10 1
  554. a10 1
  555. static char rcsid[] = "$Header: fs.c,v 1.4 86/07/24 11:32:59 brent Exp $ SPRITE (Berkeley)";
  556. d72 1
  557. d89 1
  558. d91 1
  559. a91 3
  560.             component[index] = *curCharPtr;
  561.             index++;
  562.             curCharPtr++;
  563. d93 4
  564. a96 1
  565.         component[index] = '\0';
  566. d109 3
  567. d333 1
  568. d337 1
  569. @
  570.  
  571.  
  572. 1.4
  573. log
  574. @Completed Fs_Read (there were a number of bugs.)
  575. @
  576. text
  577. @d10 1
  578. a10 1
  579. static char rcsid[] = "$Header: fs.c,v 1.3 86/07/21 09:35:02 brent Exp $ SPRITE (Berkeley)";
  580. d81 1
  581. a81 1
  582.     if (curHandlePtr->fileType != FS_DIRECTORY) {
  583. a127 1
  584.  
  585. d149 2
  586. a150 2
  587.     if (lastByte > handlePtr->lastByte) {
  588.     lastByte = handlePtr->lastByte;
  589. d176 1
  590. a176 1
  591.         status = FsBlockIO(FS_READ, &handlePtr->device, blockAddr,
  592. d183 1
  593. a183 1
  594.         status = FsBlockIO(FS_READ, &handlePtr->device, blockAddr,
  595. d284 1
  596. a284 1
  597.     handlePtr->fileID.fileNumber = fileNumber;
  598. d287 4
  599. a290 4
  600.     handlePtr->domainToken = (ClientData)descPtr;
  601.     handlePtr->device = fsDevice;
  602.     handlePtr->fileType = descPtr->fileType;
  603.     handlePtr->lastByte = descPtr->lastByte;
  604. @
  605.  
  606.  
  607. 1.3
  608. log
  609. @Added stuf for Fs_Open
  610. @
  611. text
  612. @d10 1
  613. a10 1
  614. static char rcsid[] = "$Header: fs.c,v 1.2 86/07/18 11:58:21 nelson Exp $ SPRITE (Berkeley)";
  615. d150 3
  616. d162 3
  617. d171 1
  618. a171 1
  619.         size = lastByte & FS_BLOCK_OFFSET_MASK + 1;
  620. d182 1
  621. a182 1
  622.         Byte_Copy(size, &(readBuffer[blockOffset]), buffer);
  623. d226 1
  624. a226 1
  625.     int length;            /* Length variable for read call */
  626. d257 1
  627. d287 1
  628. a287 1
  629.     FsGetFileDesc(fsDomainPtr, fileNumber, descPtr);
  630. d291 1
  631. d328 3
  632. @
  633.  
  634.  
  635. 1.2
  636. log
  637. @Trimmed.
  638. @
  639. text
  640. @d10 1
  641. a10 1
  642. static char rcsid[] = "$Header: fs.c,v 1.1 86/07/18 09:32:17 brent Exp $ SPRITE (Berkeley)";
  643. d17 1
  644. d19 1
  645. d21 10
  646. a30 1
  647. extern    FsDomainHeader    *fsDomainPtr;
  648. d33 11
  649. d48 67
  650. d169 1
  651. a169 1
  652.             fsDomainPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK;
  653. d171 1
  654. a171 1
  655.         status = FsBlockIO(handlePtr, blockAddr,
  656. d178 2
  657. a179 2
  658.         status = FsBlockIO(handlePtr, blockAddr, FS_FRAGMENTS_PER_BLOCK,
  659.                  &(buffer[bufferIndex]));
  660. d194 126
  661. @
  662.  
  663.  
  664. 1.1
  665. log
  666. @Initial revision
  667. @
  668. text
  669. @d10 1
  670. a10 1
  671. static char rcsid[] = "$Header: vmSunBoot.c,v 1.9 86/05/01 23:20:11 nelson Exp $ SPRITE (Berkeley)";
  672. d19 1
  673. d42 5
  674. a46 5
  675.     register    FsHandle    *handlePtr;
  676.     int        offset;
  677.     int        numBytes;
  678.     Address    buffer;
  679.     int        *readCountPtr;
  680. d48 10
  681. a57 9
  682.     int            firstBlock;
  683.     int            lastBlock;
  684.     int            lastByte;
  685.     ReturnStatus    status;
  686.     BlockIndexInfo    indexInfo;
  687.     int            bufferIndex;
  688.     int            blockOffset;
  689.     int            size;
  690.     int            readSize;
  691. d79 2
  692. d82 1
  693. a82 1
  694.         status = FsFileBlockIO(handlePtr, indexInfo.blockAddr,
  695. d89 1
  696. a89 2
  697.         status = FsFileBlockIO(handlePtr, indexInfo.blockAddr,
  698.                  FS_FRAGMENTS_PER_BLOCK,
  699. @
  700.